package exam_serv

import (
	"strconv"
	"strings"
	"ubt-aio-service/app/mod/exam_mod"
	"ubt-aio-service/app/pkg/db"
	"ubt-aio-service/app/utils"
)

type examLog struct{}

var ExamLogServ = examLog{}

// OneExam 获取试卷详情
func (s *examLog) OneExam(examId string) *utils.ResJson {
	sqlStr := "SELECT a.exam_id, a.title, a.score, a.exam_time, a.begin_time, a.img_names, a.img_urls, a.remarks, a.states, a.add_time, a.upd_time FROM exam_info a WHERE a.states=1 AND a.exam_id=$1 AND EXTRACT(epoch FROM NOW())>a.begin_time AND a.end_time>EXTRACT(epoch FROM NOW())"
	return db.GetOne(sqlStr, examId)
}

// ListQsts 随机获取特定题型、特定数量的题
func (s *examLog) ListQsts(req *exam_mod.QstSelReq) *utils.ResJson {
	sqlStr := "SELECT a.qst_id, a.kind, a.qst_no, a.title, a.file_names, a.file_urls, a.answer, a.keywords, a.states, a.add_time FROM exam_base a WHERE a.states=1 AND a.kind=$1 ORDER BY random() limit $2"
	return db.GetAll(sqlStr, req.Kind, req.Limit)
}

// ListOpts 获取答案选项列表
func (s *examLog) ListOpts() *utils.ResJson {
	sqlStr := "SELECT a.opt_id, a.qst_id, a.opt_no, a.opt_name, a.img_names, a.img_urls, a.iz_right, a.answer, a.keywords, a.remarks, a.states, a.add_time, a.upd_time FROM exam_option a WHERE a.states=1 ORDER BY a.qst_id, a.opt_no"
	return db.GetAll(sqlStr)
}

// ListOpts 获取答案选项列表
//func (s *examLog) ListOpts() []map[string]any {
//	var res []map[string]any
//	ctx := context.Background()
//	if optList, err := db.RdsCli.Get(ctx, "opts").Result(); err == nil && optList != "" {
//		if err = json.Unmarshal([]byte(optList), &res); err == nil {
//			return res
//		}
//	}
//	return nil
//}

// Add 新增
func (s *examLog) Add(req *exam_mod.ExamLogSaveReq) *utils.ResJson {
	// 去掉主键，改为自动赋值模式
	sqlStr := "INSERT INTO exam_log(log_id, real_name, mobile, work_no, dept_name, exam_id, qst_ids, score, test_time, remarks, states, add_time, upd_time) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, 1, EXTRACT(epoch FROM NOW()), EXTRACT(epoch FROM NOW()))"
	return db.CudData(sqlStr, req.LogId, req.RealName, req.Mobile, req.WorkNo, req.DeptName, req.ExamId, req.QstIds, req.Score, req.TestTime, req.Remarks)
}

// AddDetails 批量新增答案选项
func (s *examLog) AddDetails(ch chan int, req []*exam_mod.ExamLogDetailReq) {
	sqlStr := "INSERT INTO exam_log_detail(log_id, exam_id, qst_id, opt_id, answer, keywords, fxd, fxd_key, sglx, sglx_key, ffcs, ffcs_key, score, remarks, states, add_time, upd_time) VALUES "
	var (
		param []any
		n     = 1
	)
	for _, dtl := range req {
		sqlStr += "($" + strconv.Itoa(n) + ", $" + strconv.Itoa(n+1) + ", $" + strconv.Itoa(n+2) + ", $" + strconv.Itoa(n+3) + ", $" + strconv.Itoa(n+4) + ", $" + strconv.Itoa(n+5) + ", $" + strconv.Itoa(n+6) + ", $" + strconv.Itoa(n+7) + ", $" + strconv.Itoa(n+8) + ", $" + strconv.Itoa(n+9) + ", $" + strconv.Itoa(n+10) + ", $" + strconv.Itoa(n+11) + ", $" + strconv.Itoa(n+12) + ", $" + strconv.Itoa(n+13) + ", 1, EXTRACT(epoch FROM NOW()), EXTRACT(epoch FROM NOW())),"
		param = append(param, dtl.LogId)
		param = append(param, dtl.ExamId)
		param = append(param, dtl.QstId)
		param = append(param, dtl.OptId)
		param = append(param, dtl.Answer)
		param = append(param, dtl.Keywords)
		param = append(param, dtl.Fxd)
		param = append(param, dtl.FxdKey)
		param = append(param, dtl.Sglx)
		param = append(param, dtl.SglxKey)
		param = append(param, dtl.Ffcs)
		param = append(param, dtl.FfcsKey)
		param = append(param, dtl.Score)
		param = append(param, dtl.Remarks)
		n += 14
	}
	sqlStr = sqlStr[:len(sqlStr)-1]
	db.CudData(sqlStr, param...)
	<-ch
}

// Deletes 删除
func (s *examLog) Deletes(logId string) *utils.ResJson {
	sqlStr := "UPDATE exam_log SET states=2, upd_time=EXTRACT(epoch FROM NOW()) WHERE log_id=$1"
	return db.CudData(sqlStr, logId)
}

// DelDetails 异步删除记录的明细数据
func (s *examLog) DelDetails(ch chan int, logId string) {
	sqlStr := "UPDATE exam_log_detail SET states=2, upd_time=EXTRACT(epoch FROM NOW()) WHERE log_id=$1"
	db.CudData(sqlStr, logId)
	<-ch
}

// One 获取详情
func (s *examLog) One(logId string) *utils.ResJson {
	sqlStr := "SELECT a.log_id, a.real_name, a.mobile, a.work_no, a.dept_name, a.exam_id, a.qst_ids, a.score AS my_score, a.test_time, a.add_time, b.title, b.begin_time, b.end_time, b.exam_time, b.score " +
		"FROM exam_log a " +
		"LEFT JOIN exam_info b ON a.exam_id=b.exam_id " +
		"WHERE a.log_id=$1"
	return db.GetOne(sqlStr, logId)
}

// ListLogQsts 获取员工选择的题类
func (s *examLog) ListLogQsts(logId string) *utils.ResJson {
	sqlStr := "SELECT a.qst_id, a.kind, a.title, a.qst_no, a.file_names, a.file_urls, a.answer, a.keywords, a.remarks " +
		"FROM exam_base a WHERE a.states=1 " +
		"AND a.qst_id IN (SELECT b.qst_id FROM exam_log_detail b WHERE b.log_id=$1) ORDER BY a.kind, a.qst_id"
	return db.GetAll(sqlStr, logId)
}

// ListLogOpts 获取详情
func (s *examLog) ListLogOpts(logId string) *utils.ResJson {
	sqlStr := "SELECT a.opt_id, a.opt_no, a.opt_name, a.answer, a.keywords, a.qst_id, a.iz_right, b.dtl_id, b.log_id, b.exam_id, " +
		"b.opt_id AS my_answer, b.fxd, b.fxd_key, b.sglx, b.sglx_key, b.ffcs, b.ffcs_key, b.score " +
		"FROM exam_option a " +
		"LEFT JOIN exam_log_detail b ON a.qst_id=b.qst_id AND b.opt_id LIKE '%'||a.opt_id||'%' AND b.log_id=$1 " +
		"WHERE a.qst_id IN (SELECT c.qst_id FROM exam_log_detail c WHERE c.log_id=$2) " +
		"ORDER BY a.qst_id, a.opt_no"
	return db.GetAll(sqlStr, logId, logId)
}

// Count 获取数量
func (s *examLog) Count(req *exam_mod.ExamLogPageReq) *utils.ResJson {
	sqlStr := "SELECT COUNT(1) AS nums FROM exam_log WHERE states=1"
	param := make([]any, 0)
	var n = 0
	if req.Keywords != "" {
		sqlStr += " AND ("
		nameArr := strings.Split(req.Keywords, " ")
		for _, name := range nameArr {
			sqlStr += "real_name LIKE '%'||$" + strconv.Itoa(n+1) + "||'%' OR " +
				"mobile LIKE '%'||$" + strconv.Itoa(n+2) + "||'%' OR " +
				"work_no LIKE '%'||$" + strconv.Itoa(n+3) + "||'%' OR "
			param = append(param, name)
			param = append(param, name)
			param = append(param, name)
			n += 3
		}
		sqlStr = sqlStr[:len(sqlStr)-4]
		sqlStr += ")"
	}
	if req.ExamId != "" {
		sqlStr += " AND exam_id=$" + strconv.Itoa(n+1)
		param = append(param, req.ExamId)
		n++
	}
	if res := db.GetOne(sqlStr, param...); res.Code == utils.Succeed.Code && res.Data.(map[string]any)["nums"].(int64) > 0 {
		return res
	}
	return utils.NoData
}

// Page 获取分页列表
func (s *examLog) Page(req *exam_mod.ExamLogPageReq) *utils.ResJson {
	sqlStr := "SELECT a.log_id, a.real_name, a.mobile, a.work_no, a.score, a.test_time, a.add_time, b.title " +
		"FROM exam_log a " +
		"LEFT JOIN exam_info b ON a.exam_id=b.exam_id " +
		"WHERE a.states=1"
	param := make([]any, 0)
	var n = 0
	if req.Keywords != "" {
		sqlStr += " AND ("
		nameArr := strings.Split(req.Keywords, " ")
		for _, name := range nameArr {
			sqlStr += "a.real_name LIKE '%'||$" + strconv.Itoa(n+1) + "||'%' OR " +
				"a.mobile LIKE '%'||$" + strconv.Itoa(n+2) + "||'%' OR " +
				"a.work_no LIKE '%'||$" + strconv.Itoa(n+3) + "||'%' OR "
			param = append(param, name)
			param = append(param, name)
			param = append(param, name)
			n += 3
		}
		sqlStr = sqlStr[:len(sqlStr)-4]
		sqlStr += ")"
	}
	if req.ExamId != "" {
		sqlStr += " AND a.exam_id=$" + strconv.Itoa(n+1)
		param = append(param, req.ExamId)
		n++
	}
	sqlStr += " ORDER BY a.add_time DESC LIMIT $" + strconv.Itoa(n+1) + " OFFSET $" + strconv.Itoa(n+2)
	param = append(param, req.Limit)
	param = append(param, req.Offset)
	return db.GetAll(sqlStr, param...)
}

// HasTested 判断是否已答过题
func (s *examLog) HasTested(req *exam_mod.WorkerInfo) *utils.ResJson {
	sqlStr := "SELECT log_id FROM exam_log " +
		"WHERE states=1 AND work_no=$1 AND exam_id=$2 " +
		"ORDER BY add_time DESC LIMIT 1"
	return db.GetOne(sqlStr, req.WorkNo, req.ExamId)
}

// AllLog 获取所有答题记录
func (s *examLog) AllLog() *utils.ResJson {
	sqlStr := "SELECT a.log_id, a.real_name, a.mobile, a.work_no, a.dept_name, a.exam_id, a.qst_ids, a.score AS my_score, a.test_time, a.add_time, b.title, b.begin_time, b.end_time, b.exam_time, b.score " +
		"FROM exam_log a " +
		"LEFT JOIN exam_info b ON a.exam_id=b.exam_id "
	return db.GetAll(sqlStr)
}
